home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / xmris / move.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  38KB  |  1,361 lines

  1. /*{{{  (C) 1992 Nathan Sidwell*/
  2. /*****************************************************************************
  3.             X M R I S V1.01
  4.             ---------------
  5.             (C) 1992 Nathan Sidwell
  6.  
  7. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  8. is in the public domain. Permission is granted to distribute and compile
  9. verbatim copies of this software for non-commercial, non-profit use,
  10. without fee. The software may be modified, provided that both the above copyright
  11. notice and this permission notice appear.
  12.  
  13. No guarantee is given as to the robustness or suitability of this
  14. software for your computer.
  15.  
  16. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  17. *****************************************************************************/
  18. /*}}}*/
  19. #include "xmris.h"
  20. /*{{{  prototypes*/
  21. static void munch_back PROTOARGLIST((int, int, int, int, int, int, SPRITE *));
  22. /*}}}*/
  23. /*{{{  unsigned choose_direction(valid)*/
  24. extern unsigned choose_direction FUNCARGLIST((valid))
  25. unsigned  valid FUNCARGTERM
  26. /* picks a direction at random from the valid ones */
  27. {
  28.   unsigned  choices;
  29.   unsigned  temp;
  30.   unsigned  choice;
  31.   
  32.   assert(valid && !(valid & ~0xF));
  33.   for(choices = 0, temp = valid; temp; choices++)
  34.     temp ^= temp & -temp;
  35.   if(choices == 1)
  36.     choice = 0;
  37.   else if(choices == 3)
  38.     choice = random() % 3;
  39.   else
  40.     choice = random() & (choices - 1);
  41.   do
  42.     {
  43.       temp = valid & -valid;
  44.       valid ^= temp;
  45.     }
  46.   while(choice--);
  47.   assert(temp);
  48.   for(valid = 0; !(temp & 1); valid++)
  49.     temp >>= 1;
  50.   return valid;
  51. }
  52. /*}}}*/
  53. /*{{{  CELL *drop_apple(aptr, cptr)*/
  54. extern CELL *drop_apple FUNCARGLIST((aptr, cptr))
  55. APPLE   *aptr FUNCARGSEP
  56. CELL    *cptr FUNCARGTERM
  57. /*
  58.  * deals with apples which break through to the cell below
  59.  * the apple has already been moved to the new coordinate
  60.  * returns NULL if we stay in the same cell, or a pointer
  61.  * to the new cell
  62.  */
  63. {
  64.   CELL      *new;
  65.   COORD     pixel;
  66.  
  67.   update.set = 0;
  68.   pixel.x = aptr->pixel.x - aptr->offset.x;
  69.   pixel.y = aptr->pixel.y - aptr->offset.y;
  70.   if(aptr->offset.y <= cptr[0].depths[1])
  71.     new = NULL;
  72.   else if(cptr[CELL_STRIDE].visit)
  73.     /*{{{  break through below*/
  74.     {
  75.       /*{{{  munch*/
  76.       {
  77.     SPRITE      *sptr;
  78.               
  79.     sptr = &sprites[SPRITE_EDGE_BASE + 1];
  80.     /*{{{  munch the left half of the edge below*/
  81.     {
  82.       unsigned  type;
  83.             
  84.       type = 0;
  85.       if(cptr[0].depths[2] < -VEL_X)
  86.         type = GAP_HEIGHT;
  87.       if(cptr[CELL_STRIDE].depths[2] < -VEL_X)
  88.         type += 2 * GAP_HEIGHT;
  89.       if(type == 3 * GAP_HEIGHT &&
  90.           (cptr[-1].depths[1] > VEL_Y ||
  91.           cptr[CELL_STRIDE-1].depths[0] < -VEL_Y))
  92.         type = 4 * GAP_HEIGHT;
  93.       munch_back(0, type,
  94.           EDGE_WIDTH >> 1, GAP_HEIGHT,
  95.           pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  96.           pixel.y + CELL_HEIGHT, sptr);
  97.       if(!cptr[0].depths[2])
  98.         munch_back(0, 0, EDGE_WIDTH >> 1, GAP_HEIGHT,
  99.         pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  100.         pixel.y + CELL_HEIGHT - GAP_WIDTH, sptr);
  101.       if(!cptr[CELL_STRIDE].depths[2])
  102.         munch_back(0, 0, EDGE_WIDTH >> 1, GAP_HEIGHT,
  103.         pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  104.         pixel.y + CELL_HEIGHT + GAP_HEIGHT, sptr);
  105.     }
  106.     /*}}}*/
  107.     /*{{{  munch the right half of the edge below*/
  108.     {
  109.       unsigned  type;
  110.             
  111.       type = 0;
  112.       if(cptr[0].depths[3] > VEL_X)
  113.         type = GAP_HEIGHT;
  114.       if(cptr[CELL_STRIDE].depths[3] > VEL_X)
  115.         type += 2 * GAP_HEIGHT;
  116.       if(type == 3 * GAP_HEIGHT &&
  117.           (cptr[1].depths[1] > VEL_Y ||
  118.           cptr[CELL_STRIDE+1].depths[0] < -VEL_Y))
  119.         type = 4 * GAP_HEIGHT;
  120.       munch_back(EDGE_WIDTH >> 1, type,
  121.           EDGE_WIDTH >> 1, GAP_HEIGHT,
  122.           pixel.x + (CELL_WIDTH >> 1),
  123.           pixel.y + CELL_HEIGHT, sptr);
  124.       if(!cptr[0].depths[3])
  125.         munch_back(EDGE_WIDTH >> 1, 0,
  126.         EDGE_WIDTH >> 1, GAP_HEIGHT,
  127.         pixel.x + (CELL_WIDTH >> 1),
  128.         pixel.y + CELL_HEIGHT - GAP_WIDTH, sptr);
  129.       if(!cptr[CELL_STRIDE].depths[3])
  130.         munch_back(EDGE_WIDTH >> 1, 0,
  131.         EDGE_WIDTH >> 1, GAP_HEIGHT,
  132.         pixel.x + (CELL_WIDTH >> 1),
  133.         pixel.y + CELL_HEIGHT + GAP_HEIGHT, sptr);
  134.     }
  135.     /*}}}*/
  136.       }
  137.       /*}}}*/
  138.       aptr->offset.y -= CELL_HEIGHT + GAP_HEIGHT;
  139.       aptr->cell.y += 1;
  140.       pixel.y += CELL_HEIGHT + GAP_HEIGHT;
  141.       global.broken = 1;
  142.       cptr[0].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  143.       new = cptr + CELL_STRIDE;
  144.       cptr[CELL_STRIDE].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  145.     }
  146.     /*}}}*/
  147.   else if(aptr->offset.y - cptr[CELL_STRIDE * 2].depths[0] >=
  148.       CELL_HEIGHT + GAP_HEIGHT)
  149.     /*{{{  breakthrough 2 below*/
  150.     {
  151.       aptr->offset.y -= CELL_HEIGHT + GAP_HEIGHT;
  152.       aptr->cell.y += 1;
  153.       pixel.y += CELL_HEIGHT + GAP_HEIGHT;
  154.       global.broken = 1;
  155.       cptr[CELL_STRIDE].visit = 1;
  156.       cptr[0].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  157.       cptr[CELL_STRIDE].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  158.       cptr[CELL_STRIDE].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  159.       cptr[CELL_STRIDE * 2].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  160.       if(cptr[CELL_STRIDE - 1].depths[3])
  161.     {
  162.       cptr[CELL_STRIDE].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  163.       cptr[CELL_STRIDE-1].depths[3] = CELL_WIDTH + GAP_WIDTH;
  164.     }
  165.       if(cptr[CELL_STRIDE+1].depths[2])
  166.     {
  167.       cptr[CELL_STRIDE].depths[3] = CELL_WIDTH + GAP_WIDTH;
  168.       cptr[CELL_STRIDE+1].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  169.     }
  170.       munch_hole(cptr + CELL_STRIDE, pixel.x, pixel.y);
  171.       new = cptr + CELL_STRIDE;
  172.     }
  173.     /*}}}*/
  174.   else
  175.     new = NULL;
  176.   /*{{{  redraw prize?*/
  177.   if(new && new->sprite)
  178.     {
  179.       SPRITE    *sptr;
  180.     
  181.       sptr = &sprites[new->sprite];
  182.       if(display.background != COLOUR_ZERO)
  183.     XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  184.         0, 0, CELL_WIDTH, CELL_HEIGHT,
  185.         pixel.x, pixel.y);
  186.       XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  187.       0, 0, CELL_WIDTH, CELL_HEIGHT,
  188.       pixel.x, pixel.y);
  189.     }
  190.   /*}}}*/
  191.   if(update.set)
  192.     add_background(update.tl.x, update.tl.y,
  193.     update.br.x - update.tl.x, update.br.y - update.tl.y);
  194.   return new;
  195. }
  196. /*}}}*/
  197. /*{{{  CELL *move_movable(mptr, cptr)*/
  198. extern CELL *move_movable FUNCARGLIST((mptr, cptr))
  199. MONSTER   *mptr FUNCARGSEP
  200. CELL      *cptr FUNCARGTERM
  201. {
  202.   unsigned  delta;
  203.   
  204.   switch(mptr->dir)
  205.   {
  206.     /*{{{  case 0: (up)*/
  207.     case 0:
  208.       if(!mptr->fast)
  209.     delta = VEL_Y;
  210.       else if(mptr->offset.y > (CELL_HEIGHT + GAP_HEIGHT) - VEL_Y_FAST * FAST_STEPS)
  211.     delta = VEL_Y_FAST;
  212.       else if(mptr->offset.y > GAP_HEIGHT + VEL_Y_FAST * FAST_STEPS)
  213.     delta = VEL_Y;
  214.       else if(mptr->offset.y > GAP_HEIGHT)
  215.     delta = VEL_Y_FAST;
  216.       else if(mptr->offset.y > 0)
  217.     delta = VEL_Y;
  218.       else if(mptr->offset.y > - VEL_Y_FAST * FAST_STEPS)
  219.     delta = VEL_Y_FAST;
  220.       else if(mptr->offset.y > - CELL_HEIGHT + VEL_Y_FAST * FAST_STEPS)
  221.     delta = VEL_Y;
  222.       else if(mptr->offset.y > - CELL_HEIGHT)
  223.     delta = VEL_Y_FAST;
  224.       else
  225.     delta = VEL_Y;
  226.       mptr->pixel.y -= delta;
  227.       mptr->offset.y -= delta;
  228.       if(mptr->offset.y == -(CELL_HEIGHT + GAP_HEIGHT))
  229.     {
  230.       mptr->offset.y = 0;
  231.       mptr->cell.y -= 1;
  232.       cptr -= CELL_STRIDE;
  233.     }
  234.       assert(cptr->visit && !mptr->offset.x && mptr->cell.y >= 0);
  235.       break;
  236.     /*}}}*/
  237.     /*{{{  case 1: (down)*/
  238.     case 1:
  239.       if(!mptr->fast)
  240.     delta = VEL_Y;
  241.       else if(mptr->offset.y < -(CELL_HEIGHT + GAP_HEIGHT) + VEL_Y_FAST * FAST_STEPS)
  242.     delta = VEL_Y_FAST;
  243.       else if(mptr->offset.y < - GAP_HEIGHT - VEL_Y_FAST * FAST_STEPS)
  244.     delta = VEL_Y;
  245.       else if(mptr->offset.y < -GAP_HEIGHT)
  246.     delta = VEL_Y_FAST;
  247.       else if(mptr->offset.y < 0)
  248.     delta = VEL_Y;
  249.       else if(mptr->offset.y < VEL_Y_FAST * FAST_STEPS)
  250.     delta = VEL_Y_FAST;
  251.       else if(mptr->offset.y < CELL_HEIGHT - VEL_Y_FAST * FAST_STEPS)
  252.     delta = VEL_Y;
  253.       else if(mptr->offset.y < CELL_HEIGHT)
  254.     delta = VEL_Y_FAST;
  255.       else
  256.     delta = VEL_Y;
  257.       mptr->pixel.y += delta;
  258.       mptr->offset.y += delta;
  259.       if(mptr->offset.y == CELL_HEIGHT + GAP_HEIGHT)
  260.     {
  261.       mptr->offset.y = 0;
  262.       mptr->cell.y += 1;
  263.       cptr += CELL_STRIDE;
  264.     }
  265.       assert(cptr->visit && mptr->cell.y < CELLS_DOWN &&
  266.       (!mptr->offset.x || (!mptr->cell.y && mptr->offset.y <= 0)));
  267.       break;
  268.     /*}}}*/
  269.     /*{{{  case 2: (left)*/
  270.     case 2:
  271.       if(!mptr->fast)
  272.     delta = VEL_X;
  273.       else if(mptr->offset.x > (CELL_WIDTH + GAP_WIDTH) - VEL_X_FAST * FAST_STEPS)
  274.     delta = VEL_X_FAST;
  275.       else if(mptr->offset.x > GAP_WIDTH + VEL_X_FAST * FAST_STEPS)
  276.     delta = VEL_X;
  277.       else if(mptr->offset.x > GAP_WIDTH)
  278.     delta = VEL_X_FAST;
  279.       else if(mptr->offset.x > 0)
  280.     delta = VEL_X;
  281.       else if(mptr->offset.x > - VEL_X_FAST * FAST_STEPS)
  282.     delta = VEL_X_FAST;
  283.       else if(mptr->offset.x > - CELL_WIDTH + VEL_X_FAST * FAST_STEPS)
  284.     delta = VEL_X;
  285.       else if(mptr->offset.x > -CELL_WIDTH)
  286.     delta = VEL_X_FAST;
  287.       else
  288.     delta = VEL_X;
  289.       mptr->pixel.x -= delta;
  290.       mptr->offset.x -= delta;
  291.       if(mptr->offset.x == -(CELL_WIDTH + GAP_WIDTH))
  292.     {
  293.       mptr->offset.x = 0;
  294.       mptr->cell.x -= 1;
  295.       cptr -= 1;
  296.     }
  297.       assert(cptr->visit && !mptr->offset.y && mptr->cell.x >= 0);
  298.       break;
  299.     /*}}}*/
  300.     /*{{{  case 3: (right)*/
  301.     case 3:
  302.       if(!mptr->fast)
  303.     delta = VEL_X;
  304.       else if(mptr->offset.x < -(CELL_WIDTH + GAP_WIDTH) + VEL_X_FAST * FAST_STEPS)
  305.     delta = VEL_X_FAST;
  306.       else if(mptr->offset.x < - GAP_WIDTH - VEL_X_FAST * FAST_STEPS)
  307.     delta = VEL_X;
  308.       else if(mptr->offset.x < -GAP_WIDTH)
  309.     delta = VEL_X_FAST;
  310.       else if(mptr->offset.x < 0)
  311.     delta = VEL_X;
  312.       else if(mptr->offset.x < VEL_X_FAST * FAST_STEPS)
  313.     delta = VEL_X_FAST;
  314.       else if(mptr->offset.x < CELL_WIDTH - VEL_X_FAST * FAST_STEPS)
  315.     delta = VEL_X;
  316.       else if(mptr->offset.x < CELL_WIDTH)
  317.     delta = VEL_X_FAST;
  318.       else
  319.     delta = VEL_X;
  320.       mptr->pixel.x += delta;
  321.       mptr->offset.x += delta;
  322.       if(mptr->offset.x == CELL_WIDTH + GAP_WIDTH)
  323.     {
  324.       mptr->offset.x = 0;
  325.       mptr->cell.x += 1;
  326.       cptr += 1;
  327.     }
  328.       assert(cptr->visit && !mptr->offset.y && mptr->cell.x < CELLS_ACROSS);
  329.       break;
  330.     /*}}}*/
  331.   }
  332.   return cptr;
  333. }
  334. /*}}}*/
  335. /*{{{  CELL *move_muncher(mptr)*/
  336. extern CELL *move_muncher FUNCARGLIST((mptr))
  337. MONSTER   *mptr FUNCARGTERM /* the object to move */
  338. /*
  339.  * moves and munches the board for an object which can munch
  340.  * apple checking is performed here too
  341.  * (ie the man, or a munch monster)
  342.  * the board array is updated as required
  343.  * returns a pointer to the new cell, if we have arrived elsewhere
  344.  * or NULL if we stayed on the same cell
  345.  */
  346. {
  347.   unsigned  broke;
  348.   CELL      *nptr;
  349.   CELL      *cherry;
  350.   CELL      *cptr;
  351.   COORD     pixel;
  352.   COORD     cell;
  353.   SPRITE    *sptr;
  354.   int       knocked;
  355.  
  356.   assert(!mptr->stop && !mptr->pause);
  357.   broke = 0;
  358.   nptr = NULL;
  359.   cherry = NULL;
  360.   update.set = 0;
  361.   cell.x = mptr->cell.x;
  362.   cell.y = mptr->cell.y;
  363.   cptr = BOARDCELL(cell.x, cell.y);
  364.   pixel.x = PIXELX(cell.x, 0);
  365.   pixel.y = PIXELY(cell.y, 0);
  366.   knocked = 0;
  367.   if(!apple_stop(mptr, cptr))
  368.     {
  369.       switch(mptr->dir)
  370.       {
  371.     /*{{{  case 0: (up)*/
  372.     case 0:
  373.       /*
  374.        * if the depth upwards is less than the future depth,
  375.        * then we have to do some munching
  376.        */
  377.       mptr->offset.y -= VEL_Y;
  378.       mptr->pixel.y = pixel.y + mptr->offset.y;
  379.       if(cptr[0].depths[0] > mptr->offset.y)
  380.         /*{{{  munch*/
  381.         {
  382.           cptr[0].depths[0] = mptr->offset.y;
  383.           sptr = &sprites[SPRITE_MUNCH_BASE + 0];
  384.           munch_back(0, 0, CELL_WIDTH, MUNCH_HEIGHT >> 1,
  385.           pixel.x, pixel.y + cptr->depths[0], sptr);
  386.           if(mptr->offset.y == -VEL_Y && cptr[-CELL_STRIDE].visit)
  387.         {
  388.           sptr = &sprites[SPRITE_EDGE_BASE + 1];
  389.           /*{{{  munch the left half of the edge above*/
  390.           {
  391.             unsigned  type;
  392.                             
  393.             type = 0;
  394.             if(cptr[0].depths[2] < -VEL_X)
  395.               type = 2 * GAP_HEIGHT;
  396.             if(cptr[-CELL_STRIDE].depths[2] < -VEL_X)
  397.               type += GAP_HEIGHT;
  398.             if(type == 3 * GAP_HEIGHT &&
  399.             (cptr[-1].depths[0] < -VEL_Y ||
  400.             cptr[-CELL_STRIDE-1].depths[1] > VEL_Y))
  401.               type = 4 * GAP_HEIGHT;
  402.             munch_back(0, type,
  403.             EDGE_WIDTH >> 1, GAP_HEIGHT,
  404.             pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  405.             pixel.y - GAP_HEIGHT, sptr);
  406.             if(!cptr[-CELL_STRIDE].depths[2])
  407.               munch_back(0, 0, EDGE_WIDTH >> 1, GAP_HEIGHT,
  408.               pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  409.               pixel.y - GAP_HEIGHT * 2, sptr);
  410.           }
  411.           /*}}}*/
  412.           /*{{{  munch the right half of the edge above*/
  413.           {
  414.             unsigned  type;
  415.                             
  416.             type = 0;
  417.             if(cptr[0].depths[3] > VEL_X)
  418.               type = 2 * GAP_HEIGHT;
  419.             if(cptr[-CELL_STRIDE].depths[3] > VEL_X)
  420.               type += GAP_HEIGHT;
  421.             if(type == 3 * GAP_HEIGHT &&
  422.             (cptr[1].depths[0] < -VEL_Y ||
  423.             cptr[-CELL_STRIDE+1].depths[1] > VEL_Y))
  424.               type = 4 * GAP_HEIGHT;
  425.             munch_back(EDGE_WIDTH >> 1, type,
  426.             EDGE_WIDTH >> 1, GAP_HEIGHT,
  427.             pixel.x + (CELL_WIDTH >> 1),
  428.             pixel.y - GAP_HEIGHT, sptr);
  429.             if(!cptr[-CELL_STRIDE].depths[3])
  430.               munch_back(EDGE_WIDTH >> 1, 0,
  431.               EDGE_WIDTH >> 1, GAP_HEIGHT,
  432.               pixel.x + (CELL_WIDTH >> 1),
  433.               pixel.y - GAP_HEIGHT * 2, sptr);
  434.           }
  435.           /*}}}*/
  436.           cptr[0].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  437.           cptr[-CELL_STRIDE].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  438.           broke = 1;
  439.         }
  440.           else
  441.         {
  442.           if(mptr->offset.y == -(VEL_Y * 2))
  443.             {
  444.               sptr = &sprites[SPRITE_EDGE_BASE + 1];
  445.               /*{{{  round top left corner?*/
  446.               if(cptr[0].depths[2] < -VEL_X)
  447.             munch_back(0, 2 * GAP_HEIGHT,
  448.                 EDGE_WIDTH >> 1, GAP_HEIGHT,
  449.                 pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  450.                 pixel.y - GAP_HEIGHT, sptr);
  451.               /*}}}*/
  452.               /*{{{  round top right corner?*/
  453.               if(cptr[0].depths[3] > VEL_X)
  454.             munch_back(EDGE_WIDTH >> 1, 2 * GAP_HEIGHT,
  455.                 EDGE_WIDTH >> 1, GAP_HEIGHT,
  456.                 pixel.x + (CELL_WIDTH >> 1),
  457.                 pixel.y - GAP_HEIGHT, sptr);
  458.               /*}}}*/
  459.             }
  460.           /*{{{  knocked through?*/
  461.           /*
  462.            * have we bumped into any of the following ?
  463.            * path from 2 above me
  464.            * path from above left
  465.            * path from above right
  466.            */
  467.           if((cptr[-CELL_STRIDE*2].depths[1] - cptr[0].depths[0] >=
  468.               CELL_HEIGHT + GAP_HEIGHT * 2) ||
  469.               (cptr[-CELL_STRIDE-1].depths[3] &&
  470.             cptr[-CELL_STRIDE-1].depths[3] - cptr[0].depths[0] >=
  471.             KNOCK_THROUGH) ||
  472.               (cptr[-CELL_STRIDE+1].depths[2] &&
  473.             cptr[-CELL_STRIDE+1].depths[2] + cptr[0].depths[0] <=
  474.             -KNOCK_THROUGH))
  475.             {
  476.               knocked = -CELL_STRIDE;
  477.               pixel.y -= CELL_HEIGHT + GAP_HEIGHT;
  478.               cell.y -= 1;
  479.             }
  480.           else
  481.             {
  482.               if(cptr->depths[0] == -(CELL_HEIGHT + GAP_HEIGHT))
  483.             {
  484.               cptr[-CELL_STRIDE].visit = 1;
  485.               cptr[-CELL_STRIDE].depths[1] =
  486.                   CELL_HEIGHT + GAP_HEIGHT;
  487.             }
  488.               cherry = cptr - CELL_STRIDE;
  489.               pixel.y -= CELL_HEIGHT + GAP_HEIGHT;
  490.             }
  491.           /*}}}*/
  492.         }
  493.         }
  494.         /*}}}*/
  495.       else if(mptr->offset.y < -VEL_Y)
  496.         {
  497.           cherry = cptr - CELL_STRIDE;
  498.           pixel.y -= CELL_HEIGHT + GAP_HEIGHT;
  499.         }
  500.       if(mptr->offset.y == -(CELL_HEIGHT + GAP_HEIGHT))
  501.         {
  502.           mptr->offset.y = 0;
  503.           mptr->cell.y--;
  504.           nptr = cptr - CELL_STRIDE;
  505.         }
  506.       break;
  507.     /*}}}*/
  508.     /*{{{  case 1: (down)*/
  509.     case 1:
  510.     {
  511.       mptr->offset.y += VEL_Y;
  512.       mptr->pixel.y = pixel.y + mptr->offset.y;
  513.       if(cptr->depths[1] < mptr->offset.y)
  514.         /*{{{  munch*/
  515.         {
  516.           cptr->depths[1] = mptr->offset.y;
  517.           sptr = &sprites[SPRITE_MUNCH_BASE + 0];
  518.           munch_back(0, MUNCH_HEIGHT >> 1,
  519.           CELL_WIDTH, MUNCH_HEIGHT >> 1,
  520.           pixel.x, pixel.y + cptr[0].depths[1] +
  521.           CELL_HEIGHT - (MUNCH_HEIGHT >> 1), sptr);
  522.           if(mptr->offset.y == VEL_Y && cptr[CELL_STRIDE].visit)
  523.         {
  524.           sptr = &sprites[SPRITE_EDGE_BASE + 1];
  525.           /*{{{  munch the left half of the edge below*/
  526.           {
  527.             unsigned  type;
  528.                             
  529.             type = 0;
  530.             if(cptr[0].depths[2] < -VEL_X)
  531.               type = GAP_HEIGHT;
  532.             if(cptr[CELL_STRIDE].depths[2] < -VEL_X)
  533.               type += 2 * GAP_HEIGHT;
  534.             if(type == 3 * GAP_HEIGHT &&
  535.             (cptr[-1].depths[1] > VEL_Y ||
  536.             cptr[CELL_STRIDE-1].depths[0] < -VEL_Y))
  537.               type = 4 * GAP_HEIGHT;
  538.             munch_back(0, type,
  539.             EDGE_WIDTH >> 1, GAP_HEIGHT,
  540.             pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  541.             pixel.y + CELL_HEIGHT, sptr);
  542.             if(!cptr[CELL_STRIDE].depths[2])
  543.               munch_back(0, 0, EDGE_WIDTH >> 1, GAP_HEIGHT,
  544.               pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  545.               pixel.y + CELL_HEIGHT + GAP_HEIGHT, sptr);
  546.           }
  547.           /*}}}*/
  548.           /*{{{  munch the right half of the edge below*/
  549.           {
  550.             unsigned  type;
  551.                             
  552.             type = 0;
  553.             if(cptr[0].depths[3] > VEL_X)
  554.               type = GAP_HEIGHT;
  555.             if(cptr[CELL_STRIDE].depths[3] > VEL_X)
  556.               type += 2 * GAP_HEIGHT;
  557.             if(type == 3 * GAP_HEIGHT &&
  558.             (cptr[1].depths[1] > VEL_Y ||
  559.             cptr[CELL_STRIDE+1].depths[0] < -VEL_Y))
  560.               type = 4 * GAP_HEIGHT;
  561.             munch_back(EDGE_WIDTH >> 1, type,
  562.             EDGE_WIDTH >> 1, GAP_HEIGHT,
  563.             pixel.x + (CELL_WIDTH >> 1),
  564.             pixel.y + CELL_HEIGHT, sptr);
  565.             if(!cptr[CELL_STRIDE].depths[3])
  566.               munch_back(EDGE_WIDTH >> 1, 0,
  567.               EDGE_WIDTH >> 1, GAP_HEIGHT,
  568.               pixel.x + (CELL_WIDTH >> 1),
  569.               pixel.y + CELL_HEIGHT + GAP_HEIGHT, sptr);
  570.           }
  571.           /*}}}*/
  572.           cptr[0].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  573.           cptr[CELL_STRIDE].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  574.           broke = 1;
  575.         }
  576.           else
  577.         {
  578.           if(mptr->offset.y == (VEL_Y * 2))
  579.             {
  580.               sptr = &sprites[SPRITE_EDGE_BASE + 1];
  581.               /*{{{  round bottom left corner?*/
  582.               if(cptr[0].depths[2] < -VEL_X)
  583.             munch_back(0, GAP_HEIGHT,
  584.                 EDGE_WIDTH >> 1, GAP_HEIGHT,
  585.                 pixel.x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  586.                 pixel.y + CELL_HEIGHT, sptr);
  587.               /*}}}*/
  588.               /*{{{  round bottom right corner?*/
  589.               if(cptr[0].depths[3] > VEL_X)
  590.             munch_back(EDGE_WIDTH >> 1, GAP_HEIGHT,
  591.                 EDGE_WIDTH >> 1, GAP_HEIGHT,
  592.                 pixel.x + (CELL_WIDTH >> 1),
  593.                 pixel.y + CELL_HEIGHT, sptr);
  594.               /*}}}*/
  595.             }
  596.           /*{{{  knocked through?*/
  597.           /*
  598.            * have we bumped into any of the following ?
  599.            * path from 2 below me
  600.            * path from below left
  601.            * path from below right
  602.            */
  603.           if((cptr[0].depths[1] - cptr[CELL_STRIDE*2].depths[0] >=
  604.               CELL_HEIGHT + GAP_HEIGHT * 2) ||
  605.               (cptr[CELL_STRIDE-1].depths[3] &&
  606.             cptr[CELL_STRIDE-1].depths[3] + cptr[0].depths[1] >=
  607.             KNOCK_THROUGH) ||
  608.               (cptr[CELL_STRIDE+1].depths[2] &&
  609.             cptr[0].depths[1] - cptr[CELL_STRIDE+1].depths[2] >=
  610.             KNOCK_THROUGH))
  611.             {
  612.               knocked = CELL_STRIDE;
  613.               pixel.y += CELL_HEIGHT + GAP_HEIGHT;
  614.               cell.y += 1;
  615.             }
  616.           else
  617.             {
  618.               if(cptr->depths[1] == (CELL_HEIGHT + GAP_HEIGHT))
  619.             {
  620.               cptr[CELL_STRIDE].visit = 1;
  621.               cptr[CELL_STRIDE].depths[0] =
  622.                   -(CELL_HEIGHT + GAP_HEIGHT);
  623.             }
  624.               cherry = cptr + CELL_STRIDE;
  625.               pixel.y += CELL_HEIGHT + GAP_HEIGHT;
  626.             }
  627.           /*}}}*/
  628.         }
  629.         }
  630.         /*}}}*/
  631.       else if(mptr->offset.y > VEL_Y)
  632.         {
  633.           cherry = cptr + CELL_STRIDE;
  634.           pixel.y += CELL_HEIGHT + GAP_HEIGHT;
  635.         }
  636.       if(mptr->offset.y == (CELL_HEIGHT + GAP_HEIGHT))
  637.         {
  638.           mptr->offset.y = 0;
  639.           mptr->cell.y++;
  640.           nptr = cptr + CELL_STRIDE;
  641.         }
  642.       break;
  643.     }
  644.     /*}}}*/
  645.     /*{{{  case 2: (left)*/
  646.     case 2:
  647.     {
  648.       mptr->offset.x -= VEL_X;
  649.       mptr->pixel.x = pixel.x + mptr->offset.x;
  650.       if(cptr[0].depths[2] > mptr->offset.x)
  651.         /*{{{  munch*/
  652.         {
  653.           cptr[0].depths[2] = mptr->offset.x;
  654.           sptr = &sprites[SPRITE_MUNCH_BASE + 1];
  655.           munch_back(0, 0, MUNCH_WIDTH >> 1, CELL_HEIGHT,
  656.           pixel.x + cptr[0].depths[2], pixel.y, sptr);
  657.           if(mptr->offset.x == -VEL_X && cptr[-1].visit)
  658.         {
  659.           sptr = &sprites[SPRITE_EDGE_BASE + 0];
  660.           /*{{{  munch the top half of the edge left*/
  661.           {
  662.             unsigned  type;
  663.                             
  664.             type = 0;
  665.             if(cptr[0].depths[0] < -VEL_Y)
  666.               type = 2 * GAP_WIDTH;
  667.             if(cptr[-1].depths[0] < -VEL_Y)
  668.               type += GAP_WIDTH;
  669.             if(type == 3 * GAP_WIDTH &&
  670.             (cptr[-CELL_STRIDE].depths[2] < -VEL_X ||
  671.             cptr[-CELL_STRIDE-1].depths[3] > VEL_X))
  672.               type = 4 * GAP_WIDTH;
  673.             munch_back(type, 0,
  674.             GAP_HEIGHT, EDGE_HEIGHT >> 1,
  675.             pixel.x - GAP_WIDTH,
  676.             pixel.y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  677.             sptr);
  678.             if(!cptr[-1].depths[0])
  679.               munch_back(0, 0, GAP_WIDTH, EDGE_HEIGHT >> 1,
  680.               pixel.x - GAP_WIDTH * 2,
  681.               pixel.y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  682.               sptr);
  683.           }
  684.           /*}}}*/
  685.           /*{{{  munch the bottom half of the edge left*/
  686.           {
  687.             unsigned  type;
  688.                             
  689.             type = 0;
  690.             if(cptr[0].depths[1] > VEL_Y)
  691.               type = 2 * GAP_WIDTH;
  692.             if(cptr[-1].depths[1] > VEL_Y)
  693.               type += GAP_WIDTH;
  694.             if(type == 3 * GAP_WIDTH &&
  695.             (cptr[CELL_STRIDE].depths[2] < -VEL_X ||
  696.             cptr[CELL_STRIDE-1].depths[3] > VEL_X))
  697.               type = 4 * GAP_WIDTH;
  698.             munch_back(type, EDGE_HEIGHT >> 1,
  699.             GAP_WIDTH, EDGE_HEIGHT >> 1,
  700.             pixel.x - GAP_WIDTH,
  701.             pixel.y + (CELL_HEIGHT >> 1), sptr);
  702.             if(!cptr[-1].depths[1])
  703.               munch_back(0, EDGE_HEIGHT >> 1,
  704.               GAP_WIDTH, EDGE_HEIGHT >> 1,
  705.               pixel.x - GAP_WIDTH * 2,
  706.               pixel.y + (CELL_HEIGHT >> 1), sptr);
  707.           }
  708.           /*}}}*/
  709.           cptr[0].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  710.           cptr[-1].depths[3] = CELL_WIDTH + GAP_WIDTH;
  711.           broke = 1;
  712.         }
  713.           else
  714.         {
  715.           if(mptr->offset.x == -(VEL_X * 2))
  716.             {
  717.               sptr = &sprites[SPRITE_EDGE_BASE + 0];
  718.               /*{{{  round left top corner?*/
  719.               if(cptr[0].depths[0] < -VEL_Y)
  720.             munch_back(2 * GAP_WIDTH, 0,
  721.                 GAP_WIDTH, EDGE_HEIGHT >> 1,
  722.                 pixel.x - GAP_WIDTH,
  723.                 pixel.y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  724.                 sptr);
  725.               /*}}}*/
  726.               /*{{{  round left bottom corner?*/
  727.               if(cptr[0].depths[1] > VEL_Y)
  728.             munch_back(2 * GAP_HEIGHT, EDGE_HEIGHT >> 1,
  729.                 GAP_WIDTH, EDGE_HEIGHT >> 1,
  730.                 pixel.x - GAP_WIDTH,
  731.                 pixel.y + (CELL_HEIGHT >> 1), sptr);
  732.               /*}}}*/
  733.             }
  734.           /*{{{  knocked through?*/
  735.           /*
  736.            * have we bumped into any of the following ?
  737.            * path from 2 left me
  738.            * path from left above
  739.            * path from left below
  740.            */
  741.           if((cptr[-2].depths[3] - cptr[0].depths[2] >=
  742.               CELL_WIDTH + GAP_WIDTH * 2) ||
  743.               (cptr[-CELL_STRIDE-1].depths[1] &&
  744.             cptr[-CELL_STRIDE-1].depths[1] - cptr[0].depths[2] >=
  745.             KNOCK_THROUGH) ||
  746.               (cptr[CELL_STRIDE-1].depths[0] &&
  747.             cptr[CELL_STRIDE-1].depths[0] + cptr[0].depths[2] <=
  748.             -KNOCK_THROUGH))
  749.             {
  750.               knocked = -1;
  751.               pixel.x -= CELL_WIDTH + GAP_WIDTH;
  752.               cell.x -= 1;
  753.             }
  754.           else
  755.             {
  756.               if(cptr->depths[2] == -(CELL_WIDTH + GAP_WIDTH))
  757.             {
  758.               cptr[-1].visit = 1;
  759.               cptr[-1].depths[3] = CELL_WIDTH + GAP_WIDTH;
  760.             }
  761.               cherry = cptr - 1;
  762.               pixel.x -= CELL_WIDTH + GAP_WIDTH;
  763.             }
  764.           /*}}}*/
  765.         }
  766.         }
  767.         /*}}}*/
  768.       else if(mptr->offset.x < -VEL_X)
  769.         {
  770.           cherry = cptr - 1;
  771.           pixel.x -= CELL_WIDTH + GAP_WIDTH;
  772.         }
  773.       if(mptr->offset.x == -(CELL_WIDTH + GAP_WIDTH))
  774.         {
  775.           mptr->offset.x = 0;
  776.           mptr->cell.x--;
  777.           nptr = cptr - 1;
  778.         }
  779.       break;
  780.     }
  781.     /*}}}*/
  782.     /*{{{  case 3: (right)*/
  783.     case 3:
  784.     {
  785.       mptr->offset.x += VEL_X;
  786.       mptr->pixel.x = pixel.x + mptr->offset.x;
  787.       if(cptr->depths[3] < mptr->offset.x)
  788.         /*{{{  munch*/
  789.         {
  790.           cptr->depths[3] = mptr->offset.x;
  791.           sptr = &sprites[SPRITE_MUNCH_BASE + 1];
  792.           munch_back(MUNCH_WIDTH >> 1, 0,
  793.           MUNCH_WIDTH >> 1, CELL_HEIGHT,
  794.           pixel.x + cptr->depths[3] +
  795.           CELL_HEIGHT - (MUNCH_WIDTH >> 1), pixel.y, sptr);
  796.           if(mptr->offset.x == VEL_X && cptr[1].visit)
  797.         {
  798.           sptr = &sprites[SPRITE_EDGE_BASE + 0];
  799.           /*{{{  munch the top half of the edge right*/
  800.           {
  801.             unsigned  type;
  802.                             
  803.             type = 0;
  804.             if(cptr[0].depths[0] < -VEL_Y)
  805.               type = GAP_WIDTH;
  806.             if(cptr[1].depths[0] < -VEL_Y)
  807.               type += 2 * GAP_WIDTH;
  808.             if(type == 3 * GAP_WIDTH &&
  809.               (cptr[-CELL_STRIDE].depths[3] > VEL_X ||
  810.             cptr[-CELL_STRIDE+1].depths[2] < -VEL_X))
  811.               type = 4 * GAP_WIDTH;
  812.             munch_back(type, 0,
  813.             GAP_WIDTH, EDGE_HEIGHT >> 1,
  814.             pixel.x + CELL_WIDTH, pixel.y +
  815.             (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1), sptr);
  816.             if(!cptr[1].depths[0])
  817.               munch_back(0, 0, GAP_WIDTH, EDGE_HEIGHT >> 1,
  818.               pixel.x + CELL_WIDTH + GAP_WIDTH, pixel.y +
  819.               (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1), sptr);
  820.           }
  821.           /*}}}*/
  822.           /*{{{  munch the bottom half of the edge right*/
  823.           {
  824.             unsigned  type;
  825.                             
  826.             type = 0;
  827.             if(cptr[0].depths[1] > VEL_Y)
  828.               type = GAP_WIDTH;
  829.             if(cptr[1].depths[1] > VEL_Y)
  830.               type += 2 * GAP_WIDTH;
  831.             if(type == 3 * GAP_WIDTH &&
  832.             (cptr[CELL_STRIDE].depths[3] > VEL_X ||
  833.             cptr[CELL_STRIDE+1].depths[2] < -VEL_X))
  834.               type = 4 * GAP_WIDTH;
  835.             munch_back(type, EDGE_HEIGHT >> 1,
  836.             GAP_WIDTH, EDGE_HEIGHT >> 1,
  837.             pixel.x + CELL_WIDTH,
  838.             pixel.y + (CELL_HEIGHT >> 1), sptr);
  839.             if(!cptr[1].depths[1])
  840.               munch_back(0, EDGE_HEIGHT >> 1,
  841.               GAP_WIDTH, EDGE_HEIGHT >> 1,
  842.               pixel.x + CELL_WIDTH + GAP_WIDTH,
  843.               pixel.y + (CELL_HEIGHT >> 1), sptr);
  844.           }
  845.           /*}}}*/
  846.           cptr[0].depths[3] = CELL_WIDTH + GAP_WIDTH;
  847.           cptr[1].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  848.           broke = 1;
  849.         }
  850.           else
  851.         {
  852.           if(mptr->offset.x == (VEL_X * 2))
  853.             {
  854.               sptr = &sprites[SPRITE_EDGE_BASE + 0];
  855.               /*{{{  round right top corner?*/
  856.               if(cptr[0].depths[0] < -VEL_Y)
  857.             munch_back(GAP_HEIGHT, 0,
  858.                 GAP_WIDTH, EDGE_HEIGHT >> 1,
  859.                 pixel.x + CELL_WIDTH, pixel.y +
  860.                 (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1), sptr);
  861.               /*}}}*/
  862.               /*{{{  round right bottom corner?*/
  863.               if(cptr[0].depths[1] > VEL_Y)
  864.             munch_back(GAP_WIDTH, EDGE_HEIGHT >> 1,
  865.                 GAP_WIDTH, EDGE_HEIGHT >> 1,
  866.                 pixel.x + CELL_WIDTH, pixel.y +
  867.                 (CELL_HEIGHT >> 1), sptr);
  868.               /*}}}*/
  869.             }
  870.           /*{{{  knocked through?*/
  871.           /*
  872.            * have we bumped into any of the following ?
  873.            * path from 2 right me
  874.            * path from right above
  875.            * path from right below
  876.            */
  877.           if((cptr[0].depths[3] - cptr[2].depths[2] >=
  878.               CELL_WIDTH + GAP_WIDTH * 2) ||
  879.               (cptr[-CELL_STRIDE+1].depths[1] &&
  880.             cptr[-CELL_STRIDE+1].depths[1] + cptr[0].depths[3] >=
  881.             KNOCK_THROUGH) ||
  882.               (cptr[CELL_STRIDE+1].depths[0] &&
  883.             cptr[0].depths[3] - cptr[CELL_STRIDE+1].depths[0] >=
  884.             KNOCK_THROUGH))
  885.             {
  886.               knocked = 1;
  887.               pixel.x += CELL_WIDTH + GAP_WIDTH;
  888.               cell.x += 1;
  889.             }
  890.           else
  891.             {
  892.               if(cptr->depths[3] == (CELL_WIDTH + GAP_WIDTH))
  893.             {
  894.               cptr[1].visit = 1;
  895.               cptr[1].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  896.             }
  897.               cherry = cptr + 1;
  898.               pixel.x += CELL_WIDTH + GAP_WIDTH;
  899.             }
  900.           /*}}}*/
  901.         }
  902.         }
  903.         /*}}}*/
  904.       else if(mptr->offset.x > VEL_X)
  905.         {
  906.           cherry = cptr + 1;
  907.           pixel.x += CELL_WIDTH + GAP_WIDTH;
  908.         }
  909.       if(mptr->offset.x == (CELL_WIDTH + GAP_WIDTH))
  910.         {
  911.           mptr->offset.x = 0;
  912.           mptr->cell.x++;
  913.           nptr = cptr + 1;
  914.         }
  915.       break;
  916.     }
  917.     /*}}}*/
  918.       }
  919.       apple_under(mptr, nptr ? nptr : cptr);
  920.     }
  921.   /*{{{  knocked through?*/
  922.   /*
  923.    * if we knocked through to an adjoining cell
  924.    * we clear out the specified cell and check all the corners
  925.    * note, cell has already been altered correctly
  926.    * we must also check to se if this launches an apple
  927.    */
  928.   if(knocked)
  929.     {
  930.       unsigned  i;
  931.       APPLE     *aptr;
  932.     
  933.       broke = 1;
  934.       cherry = cptr += knocked;
  935.       cptr[0].visit = 1;
  936.       /*{{{  alter the depths*/
  937.       {
  938.     if(cptr[-CELL_STRIDE].depths[1])
  939.       {
  940.         cptr[0].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  941.         cptr[-CELL_STRIDE].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  942.       }
  943.     if(cptr[CELL_STRIDE].depths[0])
  944.       {
  945.         cptr[0].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  946.         cptr[CELL_STRIDE].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  947.       }
  948.     if(cptr[-1].depths[3])
  949.       {
  950.         cptr[0].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  951.         cptr[-1].depths[3] = CELL_WIDTH + GAP_WIDTH;
  952.       }
  953.     if(cptr[1].depths[2])
  954.       {
  955.         cptr[0].depths[3] = CELL_WIDTH + GAP_WIDTH;
  956.         cptr[1].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  957.       }
  958.       }
  959.       /*}}}*/
  960.       munch_hole(cptr, pixel.x, pixel.y);
  961.       /*{{{  now see if we launch any apples*/
  962.       for(aptr = apple.list, i = apple.apples; i--; aptr++)
  963.     {
  964.       if(aptr->state > 1 || pixel.x - aptr->pixel.x > CELL_WIDTH / 2 ||
  965.           pixel.x - aptr->pixel.x < -CELL_WIDTH / 2)
  966.         /*EMPTY*/;
  967.       else if(pixel.y - aptr->pixel.y > CELL_HEIGHT ||
  968.           pixel.y - aptr->pixel.y < 0)
  969.         /*EMPTY*/;
  970.       else
  971.         {
  972.           /*{{{  move apple cell.x?*/
  973.           if(aptr->cell.x < cell.x)
  974.         {
  975.           aptr->cell.x += 1;
  976.           aptr->offset.x -= CELL_WIDTH + GAP_WIDTH;
  977.         }
  978.           else if(aptr->cell.x > cell.x)
  979.         {
  980.           aptr->cell.x -= 1;
  981.           aptr->offset.x += CELL_WIDTH + GAP_WIDTH;
  982.         }
  983.           /*}}}*/
  984.           if(pixel.y - aptr->pixel.y == CELL_HEIGHT && !cptr[0].depths[1])
  985.         {
  986.           if(!aptr->state)
  987.             {
  988.               aptr->state = 1;
  989.               aptr->count = APPLE_ROCK_DELAY;
  990.             }
  991.         }
  992.           else
  993.         {
  994.           aptr->state = 1;
  995.           aptr->count = 1;
  996.         }
  997.         }
  998.     }
  999.       /*}}}*/
  1000.     }
  1001.   /*}}}*/
  1002.   /*{{{  redraw or blank prize?*/
  1003.   if(cherry && cherry->sprite)
  1004.     {
  1005.       SPRITE    *sptr;
  1006.       
  1007.       if(!nptr || cherry->sprite == SPRITE_DEN ||
  1008.       cherry->sprite == SPRITE_NORMAL + 2 ||
  1009.       (cherry->sprite != SPRITE_CHERRY && mptr->type != 4))
  1010.     {
  1011.       sptr = &sprites[cherry->sprite];
  1012.       if(display.background != COLOUR_ZERO)
  1013.         XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  1014.         0, 0, CELL_WIDTH, CELL_HEIGHT, pixel.x, pixel.y);
  1015.       XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  1016.           0, 0, CELL_WIDTH, CELL_HEIGHT, pixel.x, pixel.y);
  1017.     }
  1018.       else if(!knocked || cherry->sprite != SPRITE_CHERRY)
  1019.     {
  1020.       sptr = &sprites[SPRITE_CENTER_BASE +
  1021.           (cherry->sprite != SPRITE_CHERRY)];
  1022.       munch_back(0, 0, CELL_WIDTH, CELL_HEIGHT,
  1023.         pixel.x, pixel.y, sptr);
  1024.     }
  1025.     }
  1026.   /*}}}*/
  1027.   if(update.set)
  1028.     add_background(update.tl.x, update.tl.y,
  1029.     update.br.x - update.tl.x, update.br.y - update.tl.y);
  1030.   if(broke || nptr)
  1031.     global.broken = 1;
  1032.   assert(!nptr || nptr->visit);
  1033.   assert(mptr->cell.y >= 0 && mptr->cell.y < CELLS_DOWN &&
  1034.       mptr->cell.x >= 0 && mptr->cell.x < CELLS_ACROSS &&
  1035.       (mptr->cell.x || mptr->offset.x >= 0) &&
  1036.       (mptr->cell.y || mptr->offset.y >= 0) &&
  1037.       (mptr->cell.x < CELLS_ACROSS - 1 || mptr->offset.x <= 0) &&
  1038.       (mptr->cell.y < CELLS_DOWN - 1 || mptr->offset.y <= 0) &&
  1039.       (!mptr->offset.x || !mptr->offset.y));
  1040.   return nptr;
  1041. }
  1042. /*}}}*/
  1043. /*{{{  void munch_back(sx, sy, width, height, dx, dy, sprite)*/
  1044. static void munch_back FUNCARGLIST((sx, sy, width, height, dx, dy, sprite))
  1045. int     sx      FUNCARGSEP
  1046. int     sy      FUNCARGSEP
  1047. int     width   FUNCARGSEP
  1048. int     height  FUNCARGSEP
  1049. int     dx      FUNCARGSEP
  1050. int     dy      FUNCARGSEP
  1051. SPRITE  *sprite FUNCARGTERM
  1052. /*
  1053.  * munches the background image with the specified sprite
  1054.  */
  1055. {
  1056.   if(display.background != COLOUR_ONE)
  1057.     XCopyArea(display.display, sprite->mask, display.back, GCN(GC_MASK),
  1058.     sx, sy, width, height, dx, dy);
  1059.   if(display.background != COLOUR_ZERO)
  1060.     XCopyArea(display.display, sprite->image, display.back, GCN(GC_BACK),
  1061.     sx, sy, width, height, dx, dy);
  1062.   bounding_box(dx, dy, width, height);
  1063.   return;
  1064. }
  1065. /*}}}*/
  1066. /*{{{  void munch_hole(cptr, x, y)*/
  1067. extern void munch_hole FUNCARGLIST((cptr, x, y))
  1068. CELL      *cptr FUNCARGSEP
  1069. int       x     FUNCARGSEP
  1070. int       y     FUNCARGTERM
  1071. /*
  1072.  * cut out the background for a whole cell, and
  1073.  * deal with connections to the adjoining cells
  1074.  */
  1075. {
  1076.   SPRITE    *sptr;
  1077.  
  1078.  
  1079.   /*{{{  cut out the center*/
  1080.   {
  1081.     sptr = &sprites[SPRITE_CENTER_BASE];
  1082.     munch_back(0, 0,
  1083.     CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  1084.     x, y,
  1085.     &sptr[!!(cptr[0].depths[0] || cptr[0].depths[2])]);
  1086.     munch_back(CELL_WIDTH >> 1, 0,
  1087.     CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  1088.     x + (CELL_WIDTH >> 1), y,
  1089.     &sptr[!!(cptr[0].depths[0] || cptr[0].depths[3])]);
  1090.     munch_back(CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  1091.     CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  1092.     x + (CELL_WIDTH >> 1), y + (CELL_HEIGHT >> 1),
  1093.     &sptr[!!(cptr[0].depths[1] || cptr[0].depths[3])]);
  1094.     munch_back(0, CELL_HEIGHT >> 1,
  1095.     CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  1096.     x, y + (CELL_HEIGHT >> 1),
  1097.     &sptr[!!(cptr[0].depths[1] || cptr[0].depths[2])]);
  1098.   }
  1099.   /*}}}*/
  1100.   sptr = &sprites[SPRITE_EDGE_BASE + 1];
  1101.   /*{{{  munch above?*/
  1102.   if(cptr[0].depths[0])
  1103.     {
  1104.       /*{{{  munch the left half of the edge above*/
  1105.       {
  1106.     unsigned  type;
  1107.         
  1108.     type = 0;
  1109.     if(cptr[0].depths[2])
  1110.       type = 2 * GAP_HEIGHT;
  1111.     if(cptr[-CELL_STRIDE].depths[2] < -VEL_X)
  1112.       type += GAP_HEIGHT;
  1113.     if(type == 3 * GAP_HEIGHT && (cptr[-1].depths[0] < -VEL_Y ||
  1114.         cptr[-CELL_STRIDE-1].depths[1] > VEL_Y))
  1115.       type = 4 * GAP_HEIGHT;
  1116.     munch_back(0, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  1117.         x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1), y - GAP_HEIGHT, sptr);
  1118.       }
  1119.       /*}}}*/
  1120.       /*{{{  munch the right half of the edge above*/
  1121.       {
  1122.     unsigned  type;
  1123.         
  1124.     type = 0;
  1125.     if(cptr[0].depths[3])
  1126.       type = 2 * GAP_HEIGHT;
  1127.     if(cptr[-CELL_STRIDE].depths[3] > VEL_X)
  1128.       type += GAP_HEIGHT;
  1129.     if(type == 3 * GAP_HEIGHT && (cptr[1].depths[0] < -VEL_Y ||
  1130.         cptr[-CELL_STRIDE+1].depths[1] > VEL_Y))
  1131.       type = 4 * GAP_HEIGHT;
  1132.     munch_back(EDGE_WIDTH >> 1, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  1133.         x + (CELL_WIDTH >> 1), y - GAP_HEIGHT, sptr);
  1134.       }
  1135.       /*}}}*/
  1136.     }
  1137.   /*}}}*/
  1138.   /*{{{  munch below?*/
  1139.   if(cptr[0].depths[1])
  1140.     {
  1141.       /*{{{  munch the left half of the edge below*/
  1142.       {
  1143.     unsigned  type;
  1144.         
  1145.     type = 0;
  1146.     if(cptr[0].depths[2])
  1147.       type = GAP_HEIGHT;
  1148.     if(cptr[CELL_STRIDE].depths[2] < -VEL_X)
  1149.       type += 2 * GAP_HEIGHT;
  1150.     if(type == 3 * GAP_HEIGHT && (cptr[-1].depths[1] > VEL_Y ||
  1151.         cptr[CELL_STRIDE-1].depths[0] < -VEL_Y))
  1152.       type = 4 * GAP_HEIGHT;
  1153.     munch_back(0, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  1154.         x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  1155.         y + CELL_HEIGHT, sptr);
  1156.       }
  1157.       /*}}}*/
  1158.       /*{{{  munch the right half of the edge below*/
  1159.       {
  1160.     unsigned  type;
  1161.         
  1162.     type = 0;
  1163.     if(cptr[0].depths[3])
  1164.       type = GAP_HEIGHT;
  1165.     if(cptr[CELL_STRIDE].depths[3] > VEL_X)
  1166.       type += 2 * GAP_HEIGHT;
  1167.     if(type == 3 * GAP_HEIGHT &&
  1168.         (cptr[1].depths[1] > VEL_Y ||
  1169.         cptr[CELL_STRIDE+1].depths[0] < -VEL_Y))
  1170.       type = 4 * GAP_HEIGHT;
  1171.     munch_back(EDGE_WIDTH >> 1, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  1172.         x + (CELL_WIDTH >> 1), y + CELL_HEIGHT, sptr);
  1173.       }
  1174.       /*}}}*/
  1175.     }
  1176.   /*}}}*/
  1177.   sptr = &sprites[SPRITE_EDGE_BASE + 0];
  1178.   /*{{{  munch left?*/
  1179.   if(cptr[0].depths[2])
  1180.     {
  1181.       /*{{{  munch the top half of the edge left*/
  1182.       {
  1183.     unsigned  type;
  1184.         
  1185.     type = 0;
  1186.     if(cptr[0].depths[0])
  1187.       type = 2 * GAP_WIDTH;
  1188.     if(cptr[-1].depths[0] < -VEL_Y)
  1189.       type += GAP_WIDTH;
  1190.     if(type == 3 * GAP_WIDTH &&
  1191.         (cptr[-CELL_STRIDE].depths[2] < -VEL_X ||
  1192.         cptr[-CELL_STRIDE-1].depths[3] > VEL_X))
  1193.       type = 4 * GAP_WIDTH;
  1194.     munch_back(type, 0, GAP_HEIGHT, EDGE_HEIGHT >> 1,
  1195.         x - GAP_WIDTH, y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  1196.         sptr);
  1197.       }
  1198.       /*}}}*/
  1199.       /*{{{  munch the bottom half of the edge left*/
  1200.       {
  1201.     unsigned  type;
  1202.         
  1203.     type = 0;
  1204.     if(cptr[0].depths[1])
  1205.       type = 2 * GAP_WIDTH;
  1206.     if(cptr[-1].depths[1] > VEL_Y)
  1207.       type += GAP_WIDTH;
  1208.     if(type == 3 * GAP_WIDTH &&
  1209.         (cptr[CELL_STRIDE].depths[2] < -VEL_X ||
  1210.         cptr[CELL_STRIDE-1].depths[3] > VEL_X))
  1211.       type = 4 * GAP_WIDTH;
  1212.     munch_back(type, EDGE_HEIGHT >> 1, GAP_WIDTH, EDGE_HEIGHT >> 1,
  1213.         x - GAP_WIDTH, y + (CELL_HEIGHT >> 1), sptr);
  1214.       }
  1215.       /*}}}*/
  1216.     }
  1217.   /*}}}*/
  1218.   /*{{{  munch right?*/
  1219.   if(cptr[0].depths[3])
  1220.     {
  1221.       /*{{{  munch the top half of the edge right*/
  1222.       {
  1223.     unsigned  type;
  1224.         
  1225.     type = 0;
  1226.     if(cptr[0].depths[0])
  1227.       type = GAP_WIDTH;
  1228.     if(cptr[1].depths[0] < -VEL_Y)
  1229.       type += 2 * GAP_WIDTH;
  1230.     if(type == 3 * GAP_WIDTH &&
  1231.         (cptr[-CELL_STRIDE].depths[3] > VEL_X ||
  1232.         cptr[-CELL_STRIDE+1].depths[2] < -VEL_X))
  1233.       type = 4 * GAP_WIDTH;
  1234.     munch_back(type, 0, GAP_WIDTH, EDGE_HEIGHT >> 1,
  1235.         x + CELL_WIDTH, y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  1236.         sptr);
  1237.       }
  1238.       /*}}}*/
  1239.       /*{{{  munch the bottom half of the edge right*/
  1240.       {
  1241.     unsigned  type;
  1242.         
  1243.     type = 0;
  1244.     if(cptr[0].depths[1])
  1245.       type = GAP_WIDTH;
  1246.     if(cptr[1].depths[1] > VEL_Y)
  1247.       type += 2 * GAP_WIDTH;
  1248.     if(type == 3 * GAP_WIDTH &&
  1249.         (cptr[CELL_STRIDE].depths[3] > VEL_X ||
  1250.         cptr[CELL_STRIDE+1].depths[2] < -VEL_X))
  1251.       type = 4 * GAP_WIDTH;
  1252.     munch_back(type, EDGE_HEIGHT >> 1, GAP_WIDTH, EDGE_HEIGHT >> 1,
  1253.         x + CELL_WIDTH, y + (CELL_HEIGHT >> 1), sptr);
  1254.       }
  1255.       /*}}}*/
  1256.     }
  1257.   /*}}}*/
  1258.   return;
  1259. }
  1260. /*}}}*/
  1261. /*{{{  void new_face(mptr)*/
  1262. extern void new_face FUNCARGLIST((mptr))
  1263. MONSTER *mptr FUNCARGTERM
  1264. /*
  1265.  * calculates the required face for the direction,
  1266.  * given the old face
  1267.  */
  1268. {
  1269.   int       dir;
  1270.   int       face;
  1271.  
  1272.   if(mptr->push)
  1273.     dir = mptr->dir ^ 1;
  1274.   else
  1275.     dir = mptr->dir;
  1276.   face = mptr->face < 6 ? mptr->face : 2 + (mptr->face & 1);
  1277.   if(mptr->apple)
  1278.     mptr->face = 8 + (face > 2);
  1279.   else if(dir & 2)
  1280.     mptr->face = dir;
  1281.   else if(face == 2)
  1282.     mptr->face = dir;
  1283.   else if(face == 3)
  1284.     mptr->face = dir + 4;
  1285.   else if((dir ^ face) & 1)
  1286.     mptr->face ^= 5;
  1287.   if(mptr->face & 2 && mptr->pushing)
  1288.     mptr->face += 4;
  1289.   return;
  1290. }
  1291. /*}}}*/
  1292. /*{{{  int valid_directions(mptr, cptr)*/
  1293. extern int valid_directions FUNCARGLIST((mptr, cptr))
  1294. MONSTER   *mptr FUNCARGSEP
  1295. CELL      *cptr FUNCARGTERM
  1296. /*
  1297.  * sets the valid and nearer direction bits
  1298.  * these are nr, nl, nd, nu, r, l, d, u
  1299.  */
  1300. {
  1301.   int       answer;
  1302.   int       offset;
  1303.  
  1304.   answer = 0;
  1305.   if(offset = mptr->offset.y)
  1306.     /*{{{  up down only*/
  1307.     {
  1308.       if(offset > cptr->depths[0])
  1309.     answer |= 0x1;
  1310.       if(offset < cptr->depths[1])
  1311.     answer |= 0x2;
  1312.       if(offset < 0 ? cptr[0].distance < cptr[-CELL_STRIDE].distance :
  1313.       cptr[0].distance >= cptr[CELL_STRIDE].distance)
  1314.     answer |= 0x20;
  1315.       else
  1316.     answer |= 0x10;
  1317.     }
  1318.     /*}}}*/
  1319.   else if(offset = mptr->offset.x)
  1320.     /*{{{  left right only*/
  1321.     {
  1322.       if(offset > cptr->depths[2])
  1323.     answer |= 0x4;
  1324.       if(offset < cptr->depths[3])
  1325.     answer |= 0x8;
  1326.       if(offset < 0 ? cptr[0].distance < cptr[-1].distance :
  1327.       cptr[0].distance >= cptr[1].distance)
  1328.     answer |= 0x80;
  1329.       else
  1330.     answer |= 0x40;
  1331.     }
  1332.     /*}}}*/
  1333.   else
  1334.     /*{{{  at intersection*/
  1335.     {
  1336.       int       distance;
  1337.       
  1338.       if(cptr->depths[0])
  1339.     answer |= 0x1;
  1340.       if(cptr->depths[1])
  1341.     answer |= 0x2;
  1342.       if(cptr->depths[2])
  1343.     answer |= 0x4;
  1344.       if(cptr->depths[3])
  1345.     answer |= 0x8;
  1346.       distance = cptr->distance;
  1347.       if(distance > cptr[-CELL_STRIDE].distance)
  1348.     answer |= 0x10;
  1349.       if(distance > cptr[CELL_STRIDE].distance)
  1350.     answer |= 0x20;
  1351.       if(distance > cptr[-1].distance)
  1352.     answer |= 0x40;
  1353.       if(distance > cptr[1].distance)
  1354.     answer |= 0x80;
  1355.     }
  1356.     /*}}}*/
  1357.   answer &= answer << 4 | 0xF;
  1358.   return answer;
  1359. }
  1360. /*}}}*/
  1361.